package utils

import "sync"

type PoolNewFun func() interface{}
type IReset interface {
	Reset()
}

// 管道对象池 线程安全
func NewChannelPool(capacity int, nf PoolNewFun) *ChannelPool {
	return &ChannelPool{
		New:   nf,
		items: make(chan interface{}, capacity),
	}
}

type ChannelPool struct {
	items chan interface{}
	New   PoolNewFun
}

func (m *ChannelPool) Put(i interface{}) {
	poolItemReset(i)
	select {
	case m.items <- i:
	default:
	}
}

func (m *ChannelPool) Get() interface{} {
	var i interface{}
	select {
	case i = <-m.items:
	default:
		i = m.New()
	}
	return i
}

// 数组对象池 非线程安全
func NewSlicePool(capacity int, nf PoolNewFun) *SlicePool {
	p := &SlicePool{
		New:   nf,
		items: make([]interface{}, capacity),
		size:  capacity,
	}

	return p
}

type SlicePool struct {
	items []interface{}
	index int
	size  int
	New   PoolNewFun
}

func (m *SlicePool) Put(i interface{}) {
	if m.index < m.size {
		poolItemReset(i)
		m.items[m.index] = i
		m.index++
	}
}

func (m *SlicePool) Get() interface{} {
	var i interface{}
	if m.index > 0 {
		m.index--
		i = m.items[m.index]
		m.items[m.index] = nil
	} else {
		i = m.New()
	}
	return i
}

// 标准库对象池
func NewStdPool(nf PoolNewFun) *StdPool {
	return &StdPool{
		p: &sync.Pool{
			New: nf,
		},
	}
}

type StdPool struct {
	p *sync.Pool
}

func (m *StdPool) Put(i interface{}) {
	poolItemReset(i)
	m.p.Put(i)
}

func (m *StdPool) Get() interface{} {
	return m.p.Get()
}

func poolItemReset(i interface{}) {
	if r, ok := i.(IReset); ok {
		r.Reset()
	}
}
